from face_recognition.face_model import FaceModel
import cv2
import numpy as np
from PIL import Image
import base64
import os
from .models import face
from .serializers import FaceSerializer
from rest_framework import viewsets
from rest_framework.response import Response
from django.http.request import QueryDict
from rest_framework import viewsets, status
from rest_framework.decorators import action
from django.shortcuts import render, get_object_or_404
from django.core.files.uploadedfile import InMemoryUploadedFile
from rest_framework.pagination import PageNumberPagination
from django_filters.rest_framework import DjangoFilterBackend

class FacePagination(PageNumberPagination):
    page_size_query_param = 'pageSize'
    page_query_param = 'pageIndex'

class FaceViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = face.objects.all().order_by('posttime')
    serializer_class = FaceSerializer
    pagination_class = FacePagination
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['name']
    recognizer = FaceModel(-1, 'face_recognition/model/model', 1)

    def create(self, request, *args, **kwargs):
        memoryFileList = request.FILES.getlist('file')

        res_failed = {}
        for memoryFile in memoryFileList:
            basename = os.path.basename(memoryFile.name)
            username = os.path.splitext(basename)[0]

            newData = QueryDict(mutable=True)
            newData.update({"name": username})
            newData.update({"url": memoryFile})

            try:
                img = self.recognizer.file2img(memoryFile.file)
                feature = self.recognizer.get_feature(img)
            except:
                res_failed[basename] = 'is not detected'
                continue

            if feature is None:
                res_failed[basename] = 'is not detected'
                continue
            base64_fea = base64.b64encode(feature)
            memoryFile.file.seek(0)
            newData.update({"feature": base64_fea.decode('utf-8')})

            serializer = self.get_serializer(
                data=newData)  # 对上传的图片序列化
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
        # self.recognizer.update_db()
        return Response(res_failed, status=status.HTTP_201_CREATED)

    #提取人脸特征
    @action(methods=['post'], detail=False)
    def get_feature(self, request, *args, **kwargs):
        memoryFile = request.FILES['img']
        img = self.recognizer.file2img(memoryFile.file)
        feature = self.recognizer.get_feature(img)

        if feature is None:
            return Response({}, status=status.HTTP_204_NO_CONTENT)
        base64_fea = base64.b64encode(feature)
        data = {"feature": base64_fea}
        return Response(data, status=status.HTTP_200_OK)
    
    # 1v1 特征比对
    @action(methods=['post'], detail=False)
    def compare_1v1(self, request, *args, **kwargs):
        print("compare_1v1")
        if ("img1" in request.data.keys() and "img2" in request.data.keys()):
            img1 = request.FILES["img1"]
            img2 = request.FILES["img2"]
            img1 = self.recognizer.file2img(img1.file)
            img2 = self.recognizer.file2img(img2.file)
            sim = self.recognizer.compare_1v1(img1, img2)
            data = {"score": sim}
            return Response(data, status=status.HTTP_200_OK)
        else:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)
    
    # 1vN 特征比对，输入一个图片文件，返回top1的底库特征相似度以及名词
    @action(methods=['post'], detail=False)
    def compare_1vn(self, request, *args, **kwargs):
        img = request.FILES['img']
        img = self.recognizer.file2img(img.file)
        face_fea = self.recognizer.get_feature(img)

        res = self.recognizer.compare_1vn(face_fea)
        if(res):
            data = {"score": res['score'],
                    "name": res['instance'].name,
                    "img":self.get_serializer(res['instance']).data['img']}
            return Response(data, status=status.HTTP_200_OK)
        else:
            return Response({})

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.img.delete()  # 删除关联的底层文件
        self.perform_destroy(instance)
        self.recognizer.update_db()
        return Response(status=status.HTTP_204_NO_CONTENT)
    
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return Response(data={'data':{'total': len(queryset), 'list': serializer.data}, 'message':'成功', 'code': '0000'}, status=status.HTTP_200_OK)

        serializer = self.get_serializer(queryset, many=True)
        return Response(data={'data':{'total': len(queryset), 'list': serializer.data}, 'message':'成功', 'code': '0000'}, status=status.HTTP_200_OK)

    @action(methods=['post'], detail=False)
    def delete(self, request,  *args, **kwargs):
        delete_id = request.query_params.get('ids', None)
        if not delete_id:
            return Response(status=status.HTTP_404_NOT_FOUND)
        for i in delete_id.split(','):
            instance = get_object_or_404(face, pk=int(i))
            instance.url.delete()  # 删除关联的底层文件
            self.perform_destroy(instance)
            self.recognizer.update_db()
        return Response(data={'data':{'total':0}, 'message':'成功', 'code': '0000'}, status=status.HTTP_200_OK)